package com.Hermes.NSP;


import com.Hermes.Omega.Omega;
import com.Hermes.Omega.PK;
import com.Hermes.Omega.SK;
import com.Hermes.User.*;
import edu.biu.scapi.exceptions.FactoriesException;
import it.unisa.dia.gas.jpbc.Element;

import javax.crypto.IllegalBlockSizeException;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;

public class getEncGraph {
    private final DX dx;
    private final Arrlist arr;
    private final PK pk;
    private final PRF_PRP_Hash pph;

    private EncGraph eg;

    public getEncGraph(ArrayList<tokenNode> _token, DX _dx, Arrlist _arr, PRF_PRP_Hash _pph, PK _pk) {
        dx = _dx;
        arr = _arr;
        pk = _pk;
        pph = _pph;


        //建立结点
        _token.forEach(tokenNode -> {
            String f4 = tokenNode.F4str;
            String t2 = tokenNode.T2str;
            int index = dx.getIndex(t2, f4);
            BigInteger kv1 = dx.getKv();//每次getindex后都会获取一次k
            ByteTools._DEBUGBYTES(kv1.toByteArray());
            var tmpvar = arr.data.get(index).data.get(0);
            BigInteger rv1 = tmpvar.getSecond();
            byte[] h2msg = ByteTools.merge(kv1.toByteArray(), rv1.toByteArray()), h2tag = new byte[32];
            pph.use_H2(h2msg, h2tag);
            ByteTools._DEBUGBYTES(h2tag);
            byte[] tmpB = ByteTools.XOR(tmpvar.getFirst(), h2tag);
            ByteTools._DEBUGBYTES(tmpB);
            byte[] bex = new byte[tmpB.length / 2], bey = new byte[tmpB.length / 2];
            System.arraycopy(tmpB, 0, bex, 0, tmpB.length / 2);
            System.arraycopy(tmpB, tmpB.length / 2, bey, 0, tmpB.length / 2);
            Element ex = pk.get_G().newElement(),
                    ey = pk.get_G().newElement();
            ex.setFromBytes(bex);
            ey.setFromBytes(bey);
            ex.getImmutable();
            ey.getImmutable();
            System.out.println("ex = " + ex);
            System.out.println("ey = " + ey);
            EncNode node = new EncNode(ex, ey, tokenNode.H1str);
            EncGraph.nodeSet.put(tokenNode, node);
        });

    }

    public static void main(String[] args) throws IllegalBlockSizeException, FactoriesException, NoSuchAlgorithmException, InvalidKeyException {
        long prest = System.currentTimeMillis();

        ConcurrentHashMap<Long, Integer> i2i = new ConcurrentHashMap<>();//id找索引
        ConcurrentHashMap<Long, Long> ii2i = new ConcurrentHashMap<>();//原始id找内部id
        ConcurrentHashMap<Long, Long> oi2i = new ConcurrentHashMap<>();//内部id找原始id
        ArrayList<node> apl = JsonUtil.getNodeList("resources/Chicago (2)/ch200junction.json", i2i, ii2i, oi2i);


        PD_oracle pd_oracle = new PD_oracle(apl.size());
        Floyd_Warshall fw = new Floyd_Warshall(apl, pd_oracle, i2i);

        fw.setup();
        fw.compute();
        fw.make_pdo();
        Omega omega = new Omega();
        SK sk = new SK();
        PK pk = omega.Gen(256, sk);
        PRF_PRP_Hash pph;
        pph = new PRF_PRP_Hash(256, sk);
        long preet = System.currentTimeMillis();
        System.out.println("预处理(preet-prest) = " + (preet - prest) + "ms");
        PreEnc preEnc = new PreEnc(apl, fw, omega, pk);

        long EncEnd = System.currentTimeMillis();
        System.out.println("(preet-preEnc) = " + (EncEnd - preet) + "ms");

        DX dx = new DX(pph, ii2i);
        for (node tmp : apl) {
            dx.add(tmp);
        }
        Arrlist arrlist = new Arrlist(fw, apl, pph, dx, preEnc, ii2i);
        long dxet = System.currentTimeMillis();
        System.out.println("(make Arr DX) = " + (dxet - EncEnd) + "ms");
        ArrayList<Long> query = new ArrayList<>();

        QueryTokenGen Gentoken = null;
        query.add(apl.get(45).id);
        query.add(apl.get(66).id);
        query.add(apl.get(27).id);
        query.add(apl.get(21).id);
        query.add(apl.get(61).id);
        query.add(apl.get(62).id);
        Gentoken = new QueryTokenGen(pph, query, ii2i);
        assert Gentoken != null;
        var token = Gentoken.getData();

        getEncGraph geg = new getEncGraph(token, dx, arrlist, pph, pk);
        EncGraph eg = new EncGraph();
        dx.writeDX("resources/DX.json");
        arrlist.WriteArrList("resources/ArrList.json");
    }
}
